//
// Created by jaesonzhang on 2024/9/12.
//

#ifndef SKIACANVASJSBINDING_JSENGINE_H
#define SKIACANVASJSBINDING_JSENGINE_H

#include <cstdlib>
#include <cstdio>
#include <cstdarg>
#include <cinttypes>
#include <cstring>
#include <cassert>
#include <unistd.h>
#include <cerrno>
#include <fcntl.h>
#include <ctime>
#include <string>
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <functional>
#include <future>
#if defined(__APPLE__)
#include <malloc/malloc.h>
#elif defined(__linux__) || defined(__GLIBC__)
#include <malloc.h>
#elif defined(__FreeBSD__)
#include <malloc_np.h>
#endif

#include "../quickjs/cutils.h"
#include "../quickjs/quickjs-libc.h"
#include "RenderCallback.h"


class JSEngine: public std::enable_shared_from_this<JSEngine> {
 public:
  JSEngine();
  void create();
  void destroy();
  void run(const std::string &path);
  void run(const char *code, int len, const std::string &filename);

 private:
  static int evalBuf(JSContext *ctx, const char *buf, int buf_len,
                     const char *filename, int eval_flags);
  static int evalFile(JSContext *ctx, const char *filename, int module);
  void processTasks();


 public:
// 将任务添加到队列中
  template<typename T>
  void enqueueTask(T &&task);

 public:
  JSRuntime *jsRuntime = nullptr;
  JSContext *jsContext = nullptr;

 private:
  bool dumpMemory = false;
  std::thread _thread;
  std::queue<std::packaged_task<void()>> tasks_;
  std::mutex task_mutex_;
  std::condition_variable task_cv_;
  bool stop_thread_;
};


#endif //SKIACANVASJSBINDING_JSENGINE_H
